/** 
 * @author Pedro J Toro
 * csc7013 Advanced Mathematics for Computer Scientists
 */
public class DiffieHellman {
	private double myBase;
	private double privateKey;
	private double myMod;
	private double myPower;
	
	/**
	 * Default constructor
	 * @param primeG, public g value
	 * @param primeN, public n value
	 */
	public DiffieHellman(double myG, double myN) {
		super();
		this.myBase = myG;
		this.myMod = myN;
	}

	/**
	 * Gets the base value of the equation.
	 * @return the baseNumber
	 */
	public double getMyBase() {
		return myBase;
	}

	/**
	 * Sets the base value of the equation.
	 * @param baseNumber the baseNumber to set
	 */
	public void setMyBase(double baseNumber) {
		this.myBase = baseNumber;
	}

	/**
	 * Gets the private key value.
	 * @return the privateKey
	 */
	public double getPrivateKey() {
		return privateKey;
	}

	/**
	 * Sets the private key value.
	 * @param privateKey the privateKey to set
	 */
	public void setPrivateKey(double privateKey) {
		this.privateKey = privateKey;
	}

	/**
	 * Gets the mod value of the equation.
	 * @return the modNumber
	 */
	public double getMyMod() {
		return myMod;
	}

	/**
	 * Sets the mod value of the equation.
	 * @param modNumber the modNumber to set
	 */
	public void setMyMod(double modNumber) {
		this.myMod = modNumber;
	}

	/**
	 * Gets the power value of the equation.
	 * @return the power
	 */
	public double getMyPower() {
		return myPower;
	}

	/**
	 * Sets the power value of the equation.
	 * @param power the power to set
	 */
	public void setMyPower(double power) {
		this.myPower = power;
	}

	/**
	 * Copies privateKey value to base value
	 */
	public void swapBases() {
		myBase = privateKey;
	}
		
	/**
	 * Public function to use in Diffe-Hellman key exchange.
	 * @param baseNumber, base number to use
	 * @return the answer
	 */
	public double publicFunction(double baseNumber) {
		return reduceEquation(baseNumber, myPower, myMod);
	}
	
	/**
	 * Recursively reduce the equation into values that can be calculated properly in Java.
	 * @param baseNumber, base number to use
	 * @param powerNumber, power number to use 
	 * @param modNumber, number to mod by
	 * @return the answer
	 */
	private double reduceEquation(double baseNumber, double powerNumber, double modNumber) {
		double halfPower = powerNumber / 2;
		
		if (powerNumber == 1) {
			return (baseNumber % modNumber);
		} else if ((powerNumber % 2) == 0) {
			return (Math.pow(reduceEquation(baseNumber, halfPower, modNumber), powerNumber/halfPower) % modNumber);
		} else {
			return (reduceEquation(baseNumber, powerNumber-1, modNumber) * reduceEquation(baseNumber, 1, modNumber)) % modNumber;
		}
	}

}
